package xcmg.device.web.warehouse;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import xcmg.device.dao.entity.barcode.BarcodeManageDO;
import xcmg.device.dao.entity.company.CompanyDealerDO;
import xcmg.device.dao.entity.company.CompanyInfoDO;
import xcmg.device.dao.entity.warehouse.WarehouseInventoryDO;
import xcmg.device.dao.mapper.BarcodeManageMapper;
import xcmg.device.dao.mapper.CompanyDealerMapper;
import xcmg.device.dao.mapper.logistics.SendBillMapper;
import xcmg.device.infra.BasicController;
import xcmg.device.infra.CompanyConstants;
import xcmg.device.infra.ErrorCode;
import xcmg.device.infra.ExportUtil;
import xcmg.device.infra.annotation.ExternalApiRequest;
import xcmg.device.infra.exception.CommonBusiExceptions;
import xcmg.device.infra.interceptor.externalApiCheck.handle.ApiCheckStrategy.ApiCheckOptionEnum;
import xcmg.device.service.agent.ServiceBasicDataAgentService;
import xcmg.device.service.basic.SystemParameterService;
import xcmg.device.service.company.CompanyInfoService;
import xcmg.device.service.crm.util.ActionResultUtil;
import xcmg.device.service.vo.FunctionResult;
import xcmg.device.service.vo.basic.WarehouseInfoConditionVO;
import xcmg.device.service.vo.basic.WarehouseStockInfoVO;
import xcmg.device.service.vo.initialInventory.MaterialsEnableStock;
import xcmg.device.service.vo.warehouse.InventoryTurnOverQueryParamVO;
import xcmg.device.service.vo.warehouse.StockAmountInfo;
import xcmg.device.service.vo.warehouse.TotalBarcodeVO;
import xcmg.device.service.vo.warehouse.WarehoseIntentionDetialVO;
import xcmg.device.service.vo.warehouse.WarehouseInOutBaseVO;
import xcmg.device.service.vo.warehouse.WarehouseInventoryHistoryReportResponse;
import xcmg.device.service.vo.warehouse.WarehouseInventoryHistoryReportVO;
import xcmg.device.service.vo.warehouse.WarehouseInventoryStockVO;
import xcmg.device.service.vo.warehouse.WarehouseInventoryTransferWithOutBarCodeVO;
import xcmg.device.service.vo.warehouse.WarehouseInventoryTurnOverResultVO;
import xcmg.device.service.vo.warehouse.WarehouseInventoryVO;
import xcmg.device.service.vo.warehouse.app.EnableAndOccupyVO;
import xcmg.device.service.vo.warehouse.app.WarehouseInventoryBatchFrozenVO;
import xcmg.device.service.vo.warehouse.app.WarehouseInventoryBatchTransferVO;
import xcmg.device.service.vo.warehouse.app.WarehouseInventoryTransferVO;
import xcmg.device.service.vo.warehouse.sap.ObligateVO;
import xcmg.device.service.warehouse.WarehouseAreaStockQueryParamVO;
import xcmg.device.service.warehouse.WarehouseAreaStockQueryResultVO;
import xcmg.device.service.warehouse.WarehouseInventoryHistoryService;
import xcmg.device.service.warehouse.WarehouseInventoryService;
import xcmg.device.util.ToolTime;
import yb.ecp.fast.infra.annotation.FastMappingInfo;
import yb.ecp.fast.infra.infra.ActionResult;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.infra.log.LogHelper;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/warehouseInventory")
public class WarehouseInventoryController extends BasicController {
    private static final String SPLIT_ERROR = "条码已拆分";
    private static final String MONTH_FORMAT_STR = "yyyy-MM";
    @Autowired
    private ServiceBasicDataAgentService serviceBasicDataAgentService;

    @Autowired
    private WarehouseInventoryHistoryService warehouseInventoryHistoryService;

    @Autowired
    private WarehouseInventoryService warehouseInventoryService;

    @Autowired
    private CompanyDealerMapper companyDealerMapper;

    @Autowired
    private BarcodeManageMapper barcodeManageMapper;

    @Autowired
    private SystemParameterService systemParameterService;

    @Autowired
    private CompanyInfoService companyInfoService;

    @Autowired
    private SendBillMapper sendBillMapper;

    @RequestMapping(value = "/itemWarehouseInfo", method = RequestMethod.POST)
    @ApiOperation("根据公司编码和零件编码查询零件可用库存")
    public ActionResult<Object> itemWarehouseInfo(@RequestBody WarehouseInfoConditionVO condition) throws Exception {
        WarehouseStockInfoVO warehouseStockInfoVO = warehouseInventoryService.itemWarehouseInfo(condition);
        return actionValueResult(warehouseStockInfoVO);
    }

    @RequestMapping(value = "/list", method = RequestMethod.POST)
    @ApiOperation("查询库存记录列表")
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> list(@RequestBody SearchCommonVO<WarehouseInventoryVO> condition) throws Exception {
        WarehouseInventoryVO warehouseInventoryVO = condition.getFilters();
        if (warehouseInventoryVO == null) {
            warehouseInventoryVO = new WarehouseInventoryVO();
        }
        warehouseInventoryVO.setOrgId(getOrgId());
        condition.setFilters(warehouseInventoryVO);
        PageCommonVO<Object> pageCommonVO = warehouseInventoryService.list(condition, getDeptId());
        return actionValueResult(pageCommonVO.getPageInfo());
    }

    @RequestMapping(value = "/enterpriseList", method = RequestMethod.POST)
    @ApiOperation("查询供应商仓库库存")
    @FastMappingInfo(needLogin = true)
    public ActionResult< PageInfo<WarehouseInventoryVO>> enterpriseList(@RequestBody SearchCommonVO<WarehouseInventoryStockVO> condition) throws Exception {
        WarehouseInventoryStockVO warehouseInventoryStockVO = condition.getFilters();
        if (warehouseInventoryStockVO == null || warehouseInventoryStockVO.getSupplierOrgId() == null) {
            throw new CommonBusiExceptions(ErrorCode.IllegalArument.getDesc());
        }
        condition.getFilters().setOrgId(getOrgId());
        CompanyDealerDO companyDealerDO = warehouseInventoryService.isStorage(condition.getFilters().getSupplierOrgId(), condition.getFilters().getOrgId());
        if (companyDealerDO == null) {
            throw new CommonBusiExceptions(ErrorCode.NotPlatform.getDesc());
        } else if (companyDealerDO.getIsStorage() == 0) {
            throw new CommonBusiExceptions(ErrorCode.NoAuthority.getDesc());
        }
        condition.getFilters().setOrgId(condition.getFilters().getSupplierOrgId());
        PageCommonVO<WarehouseInventoryVO> pageCommonVO = warehouseInventoryService.enterpriseStockList(condition, getDeptId());
        return actionValueResult(pageCommonVO.getPageInfo());
    }

    @RequestMapping(value = "/detailList", method = RequestMethod.POST)
    @ApiOperation("查询库存详情")
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> detailList(@RequestBody SearchCommonVO<WarehouseInventoryVO> condition) throws Exception {
        WarehouseInventoryVO warehouseInventoryVO = condition.getFilters();
        if (warehouseInventoryVO == null) {
            warehouseInventoryVO = new WarehouseInventoryVO();
        }
        warehouseInventoryVO.setOrgId(getOrgId());
        condition.setFilters(warehouseInventoryVO);
        PageCommonVO<Object> pageCommonVO = warehouseInventoryService.detailList(condition);
        return actionValueResult(pageCommonVO.getPageInfo());
    }

    @RequestMapping(value = "/listForCollect", method = RequestMethod.POST)
    @ApiOperation("查询库存详情")
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> listForCollect(@RequestBody SearchCommonVO<WarehouseInventoryVO> condition) throws Exception {
        WarehouseInventoryVO warehouseInventoryVO = condition.getFilters();
        if (warehouseInventoryVO == null) {
            warehouseInventoryVO = new WarehouseInventoryVO();
        }
        warehouseInventoryVO.setOrgId(getOrgId());
        condition.setFilters(warehouseInventoryVO);
        PageCommonVO<Object> pageCommonVO = warehouseInventoryService.listForCollect(condition);
        return actionValueResult(pageCommonVO.getPageInfo());
    }

    @RequestMapping(value = "/listForPDA", method = RequestMethod.POST)
    @ApiOperation("用于pda库存查询")
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> listForPDA(@RequestBody SearchCommonVO<WarehouseInventoryVO> condition) throws Exception {
        WarehouseInventoryVO warehouseInventoryVO = condition.getFilters();
        if (warehouseInventoryVO == null) {
            warehouseInventoryVO = new WarehouseInventoryVO();
        }
        warehouseInventoryVO.setOrgId(getOrgId());
        condition.setFilters(warehouseInventoryVO);
        try {
            List<WarehouseInventoryDO> inventoryDOList = warehouseInventoryService.listForPDA(condition, getUserId(), getDeptId());
            return actionValueResult(new PageInfo<WarehouseInventoryDO>(inventoryDOList));
        } catch (Exception e) {
            return new ActionResult<>(ErrorCode.Failure.getCode(), e.getMessage());
        }
    }

    @RequestMapping(value = "/listForDealer", method = RequestMethod.POST)
    @ApiOperation("查询客户库存记录列表")
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> listForDealer(@RequestBody SearchCommonVO<WarehouseInventoryVO> condition) throws Exception {
        String orgId = getOrgId();
        if (StringUtils.isNotBlank(condition.getFilters().getSupplierOrgId())) {
            orgId = condition.getFilters().getSupplierOrgId();
        }
        if (StringUtils.isNotBlank(condition.getFilters().getOrgId())) {
            CompanyDealerDO companyDealerDO = companyDealerMapper.item(Long.valueOf(condition.getFilters().getOrgId()));
            if (companyDealerDO != null && companyDealerDO.getIsPlatCompany()) {
                condition.getFilters().setDealerOrgId(companyDealerDO.getPlatOrgId());
            } else {
                return actionValueResult(new ArrayList<>());
            }
        }
        condition.getFilters().setOrgId(orgId);
        PageCommonVO<Object> pageCommonVO = warehouseInventoryService.listForDealer(condition);
        return actionValueResult(pageCommonVO.getPageInfo());
    }

    @RequestMapping(value = "/selectCustomerList", method = RequestMethod.POST)
    @ApiOperation("根据orgId查询客户库存记录列表")
    @FastMappingInfo(needLogin = true)
    public ActionResult<PageInfo<WarehouseInventoryVO>> selectCustomerList(@RequestBody SearchCommonVO<WarehouseInventoryStockVO> condition) throws Exception {
        WarehouseInventoryStockVO warehouseInventoryStockVO = condition.getFilters();
        if (warehouseInventoryStockVO == null) {
            throw new CommonBusiExceptions(ErrorCode.IllegalArument.getDesc());
        }
        condition.getFilters().setOrgId(getOrgId());
        if (condition.getFilters().getSupplierOrgId() != null) {
            CompanyDealerDO companyDealerDO = warehouseInventoryService.isStorage(condition.getFilters().getSupplierOrgId(), condition.getFilters().getOrgId());
            if (companyDealerDO == null) {
                throw new CommonBusiExceptions(ErrorCode.NotPlatform.getDesc());
            } else if (companyDealerDO.getIsStorage() == 0) {
                throw new CommonBusiExceptions(ErrorCode.NoAuthority.getDesc());
            }
        }
        if (condition.getFilters().getDealerOrgId() == null) {
            return actionValueResult(new PageInfo<>());
        }
        condition.getFilters().setOrgId(condition.getFilters().getDealerOrgId());
        PageCommonVO<WarehouseInventoryVO> pageCommonVO = warehouseInventoryService.enterpriseStockList(condition, getDeptId());
        return actionValueResult(pageCommonVO.getPageInfo());
    }

    @RequestMapping(value = "/remove", method = RequestMethod.POST)
    @ApiOperation("库存记录删除")
    @FastMappingInfo(needLogin = true)
    public ActionResult<String> remove(@RequestBody String[] ids) {
        if (ids == null || ids.length == 0) {
            return actionResult(ErrorCode.IllegalArument);
        }
        return actionResult(warehouseInventoryService.remove(Arrays.asList(ids)));
    }

    @RequestMapping(value = "/item", method = RequestMethod.GET)
    @ApiOperation(value = "根据主键查找单条记录详情")
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> item(String id) {
        return actionValueResult(warehouseInventoryService.findByPK(id));
    }

    @RequestMapping(value = "/itemByBarcodeForSplit", method = RequestMethod.GET)
    @ApiOperation(value = "根据条码查找单条记录详情")
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> itemByBarcodeForSplit(String barcode) {
        try {
            return actionValueResult(warehouseInventoryService.findByBarCodeForSplit(barcode, getOrgId()));
        } catch (Exception e) {
            return new ActionResult<>(ErrorCode.Failure.getCode(), e.getMessage());
        }
    }

    @RequestMapping(value = "/findByBarcode", method = RequestMethod.GET)
    @ApiOperation(value = "条码查询库存零件情况-外部接口调用")
    @ExternalApiRequest(ApiCheckOptionEnum.OPTION_SECRET)
    public ActionResult<Object> findByBarcode(String barcode, String sapCode) {
        try {
            List<WarehouseInventoryVO> inventoryVOList = new ArrayList<>();
            CompanyInfoDO companyInfoDO = companyInfoService.getBySapCode(sapCode);
            if (null == companyInfoDO) {
                return new ActionResult<>(ErrorCode.Failure.getCode(), "公司信息不存在");
            }

            BarcodeManageDO barcodeDO = barcodeManageMapper.item(barcode, companyInfoDO.getOrgId());
            if (barcodeDO != null && barcodeDO.getBarcodeFlag() == 1 && "3"
                    .equals(barcodeDO.getBarcodeStatus())) {
                return new ActionResult<>(ErrorCode.Failure.getCode(), SPLIT_ERROR,
                        inventoryVOList);
            }
            return actionValueResult(warehouseInventoryService.findByAllBarCode(barcode, companyInfoDO.getOrgId()));
        } catch (Exception e) {
            return new ActionResult<>(ErrorCode.Failure.getCode(), e.getMessage());
        }
    }

//    @RequestMapping(value = "/queryByBarcode4Cy", method = RequestMethod.GET)
//    @ApiOperation(value = "条码查询库存零件情况-外部接口调用(铲运使用)")
//    @ExternalApiRequest(ApiCheckOptionEnum.OPTION_SECRET)
//    public ActionResult<Object> queryByCyBarcode(String barcode, String sapCode) {
//        try {
//            List<WarehouseInventoryCyVO> inventoryVOList = new ArrayList<>();
//            CompanyInfoDO companyInfoDO = companyInfoService.getBySapCode(sapCode);
//            if (null == companyInfoDO) {
//                return new ActionResult<>(ErrorCode.Failure.getCode(), "公司信息不存在");
//            }
//
//            BarcodeManageDO barcodeDO = barcodeManageMapper.item(barcode, companyInfoDO.getOrgId());
//            if (barcodeDO != null && barcodeDO.getBarcodeFlag() == 1 && "3"
//                    .equals(barcodeDO.getBarcodeStatus())) {
//                return new ActionResult<>(ErrorCode.Failure.getCode(), SPLIT_ERROR, inventoryVOList);
//            }
//            return actionResult(warehouseInventoryService.queryByCyBarcode(barcodeDO, companyInfoDO.getOrgId()));
//        } catch (Exception e) {
//            return new ActionResult<>(ErrorCode.Failure.getCode(), e.getMessage());
//        }
//    }

    @RequestMapping(value = "/itemByBarcode", method = RequestMethod.GET)
    @ApiOperation(value = "根据条码查找单条记录详情")
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> itemByBarcode(String barcode) throws Exception {
        List<WarehouseInventoryVO> inventoryVOList = new ArrayList<>();
        BarcodeManageDO barcodeDO = barcodeManageMapper.item(barcode, getOrgId());
        if (barcodeDO != null && barcodeDO.getBarcodeFlag() == 1 && "3".equals(barcodeDO.getBarcodeStatus())) {
            return new ActionResult<>(ErrorCode.Failure.getCode(), SPLIT_ERROR, inventoryVOList);
        }
        return actionValueResult(warehouseInventoryService.findByAllBarCode(barcode, getOrgId()));
    }

    @RequestMapping(value = "/itemByBarcodeForBoxup", method = RequestMethod.GET)
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> itemByBarcodeForBoxup(@RequestParam("barcode") String barcode, @RequestParam("receiptNo") String receiptNo) throws Exception {
        List<WarehouseInventoryVO> inventoryVOList = new ArrayList<>();
        String orgId = getOrgId();
        BarcodeManageDO barcodeDO = barcodeManageMapper.item(barcode, orgId);
        if (barcodeDO != null && barcodeDO.getBarcodeFlag() == 1 && "3".equals(barcodeDO.getBarcodeStatus())) {
            return new ActionResult<>(ErrorCode.Failure.getCode(), SPLIT_ERROR, inventoryVOList);
        }
        try {
            return actionValueResult(warehouseInventoryService.findByBarcodeForBoxUp(barcode, receiptNo, orgId));
        } catch (Exception e) {
            return new ActionResult<>(ErrorCode.Failure.getCode(), e.getMessage());
        }

    }

    @RequestMapping(value = "/itemByBarcodeFromInventory", method = RequestMethod.POST)
    @ApiOperation(value = "根据条码查找库存详情")
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> itemByBarcodeFromInventory(@RequestBody TotalBarcodeVO totalBarcodeVO) throws Exception {
        LogHelper.monitor("出入库入参为:" + JSON.toJSONString(totalBarcodeVO));
        List<WarehouseInventoryVO> inventoryVOList = new ArrayList<>();
        String orgId = StringUtils.isBlank(totalBarcodeVO.getOrgId()) ? getOrgId() : totalBarcodeVO.getOrgId();
        BarcodeManageDO barcodeDO = barcodeManageMapper.item(totalBarcodeVO.getBarcode(), orgId);
        if (barcodeDO != null && barcodeDO.getBarcodeFlag() == 1 && "3".equals(barcodeDO.getBarcodeStatus())) {
            return new ActionResult<>(ErrorCode.Failure.getCode(), SPLIT_ERROR, inventoryVOList);
        }

        /**
         if (barcodeDO != null && StringUtils.isNotEmpty(barcodeDO.getBillNo())) {
         SendBillDO sendBillDO = sendBillMapper.findBySendOrder(barcodeDO.getBillNo(), orgId);
         if (sendBillDO != null && !Integer.valueOf(1).equals(sendBillDO.getIsSign()) && !Integer.valueOf(3).equals(sendBillDO.getIsSign())) {
         return new ActionResult<>(ErrorCode.Failure.getCode(), "发货单状态不是签收状态，不允许入库");
         }
         }
         */

        ErrorCode code = ErrorCode.Success;
        try {
            if (totalBarcodeVO.getInbound() != null && totalBarcodeVO.getInbound() == 1) {
                inventoryVOList = warehouseInventoryService.findByBarCodeForInbound(totalBarcodeVO.getBarcode(), totalBarcodeVO.getBusinessOrder(), getUserId(), orgId);
            } else {
                code = warehouseInventoryService.findByBarCodeFromInventory(totalBarcodeVO.getBusinessOrder(), totalBarcodeVO.getBarcode(), orgId, inventoryVOList, totalBarcodeVO.getFrozen());
            }
            //获取是否关键件属性
            warehouseInventoryService.getCrucialDevice(inventoryVOList);
        } catch (Exception e) {
            LogHelper.error(getExceptionAllinformation(e), ErrorCode.Failure.getCode());
            return new ActionResult<>(ErrorCode.Failure.getCode(), e.getMessage());
        }
        LogHelper.monitor("出入库出参为:" + JSON.toJSONString(inventoryVOList));
        return actionResult(code, inventoryVOList);
    }

    @RequestMapping(value = "/itemByBatchBarcodeFromInventory", method = RequestMethod.POST)
    @ApiOperation(value = "根据条码批量查找库存详情")
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> itemByBatchBarcodeFromInventory(@RequestBody List<TotalBarcodeVO> totalBarcodeVOList) throws Exception {
        if (CollectionUtils.isEmpty(totalBarcodeVOList)) {
            throw new CommonBusiExceptions("参数不能为空!");
        }
        ErrorCode code = ErrorCode.Success;
        List<WarehouseInventoryVO> inventoryVOList = new ArrayList<>();
        for (TotalBarcodeVO totalBarcodeVO : totalBarcodeVOList) {
            LogHelper.monitor("出入库入参为:" + JSON.toJSONString(totalBarcodeVO));
            BarcodeManageDO barcodeDO = barcodeManageMapper.item(totalBarcodeVO.getBarcode(), getOrgId());
            boolean splited = checkSplited(barcodeDO);
            if (splited) {
                throw new CommonBusiExceptions("条码已拆分!");
            }
            /**
             checkSendOrderStatus(barcodeDO);
             */
            try {
                if (totalBarcodeVO.getInbound() != null && totalBarcodeVO.getInbound() == 1) {
                    inventoryVOList = warehouseInventoryService.findByBarCodeForInbound(totalBarcodeVO.getBarcode(), totalBarcodeVO.getBusinessOrder(), getUserId(), getOrgId());
                } else {
                    code = warehouseInventoryService.findByBarCodeFromInventory(totalBarcodeVO.getBusinessOrder(), totalBarcodeVO.getBarcode(), getOrgId(), inventoryVOList, totalBarcodeVO.getFrozen());
                }
            } catch (Exception e) {
                LogHelper.error(getExceptionAllinformation(e), ErrorCode.Failure.getCode());
                throw new CommonBusiExceptions(e.getMessage());
            }
        }

        return actionResult(code, inventoryVOList);
    }

//    private void checkSendOrderStatus(BarcodeManageDO barcodeDO) throws Exception {
//        if (barcodeDO != null && StringUtils.isNotEmpty(barcodeDO.getBillNo())) {
//            SendBillDO sendBillDO = sendBillMapper.findBySendOrder(barcodeDO.getBillNo(), getOrgId());
//            if (sendBillDO != null && !Integer.valueOf(1).equals(sendBillDO.getIsSign()) && !Integer.valueOf(3).equals(sendBillDO.getIsSign())) {
//                throw new CommonBusiExceptions("发货单状态不是签收状态，不允许入库");
//            }
//        }
//    }

    private boolean checkSplited(BarcodeManageDO barcodeDO) {
        return barcodeDO != null && barcodeDO.getBarcodeFlag() == 1 && "3".equals(barcodeDO.getBarcodeStatus());
    }

    @RequestMapping(value = "/transferByMaterial", method = RequestMethod.POST)
    @ApiOperation(value = "根据条码和新储位进行零件转移")
    @FastMappingInfo(needLogin = true)
    public ActionResult<List<WarehouseInventoryTransferVO>> transferByMaterial(@RequestBody WarehouseInventoryBatchTransferVO batchTransferVO) {
        if (null == batchTransferVO) {
            throw new CommonBusiExceptions(ErrorCode.IllegalArument.getDesc());
        }
        FunctionResult<List<WarehouseInventoryTransferVO>> result = new FunctionResult<>();
        List<WarehouseInventoryTransferVO> errorList = new ArrayList<>();
        try {
            ErrorCode errorCode = warehouseInventoryService.batchTransferByMaterial(batchTransferVO, getUserId(), getOrgId());
            result.setCode(errorCode);
        } catch (Exception e) {
            WarehouseInventoryTransferVO recordAddVO = batchTransferVO.getRecordList().get(getIndex(e.getMessage()));
            recordAddVO.setRemark(getMsg(e.getMessage()));
            errorList.add(recordAddVO);
            for (int i = 0; i < batchTransferVO.getRecordList().size(); i++) {
                if (i != getIndex(e.getMessage())) {
                    errorList.add(batchTransferVO.getRecordList().get(i));
                }
            }
            result.setCode(ErrorCode.Failure);
            result.setValue(errorList);
            LogHelper.monitor(getExceptionAllinformation(e));
        }
        return actionResult(result.getCode(), result.getValue());
    }

    @RequestMapping(value = "/transferByLocation", method = RequestMethod.POST)
    @ApiOperation(value = "根据新储位和旧储位进行零件转移")
    @FastMappingInfo(needLogin = true)
    public ActionResult<String> transferByLocation(String oldLocationCode, String newLocationCode) {
        try {
            return actionResult(warehouseInventoryService.transferByLocation(oldLocationCode, newLocationCode, getOrgId(), getUserId()));
        } catch (Exception e) {
            return new ActionResult<>(ErrorCode.Failure.getCode(), e.getMessage());
        }
    }

    @RequestMapping(value = "/listForInOutRecord", method = RequestMethod.POST)
    @ApiOperation("查询出入库记录")
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> listForInOutRecord(@RequestBody SearchCommonVO<WarehouseInOutBaseVO> condition) throws Exception {
        WarehouseInOutBaseVO warehouseInOutBaseVO = condition.getFilters();
        if (warehouseInOutBaseVO == null) {
            warehouseInOutBaseVO = new WarehouseInOutBaseVO();
        }
        warehouseInOutBaseVO.setOrgId(getOrgId());
        condition.setFilters(warehouseInOutBaseVO);
        PageCommonVO<Object> pageCommonVO = warehouseInventoryService.listForInOutRecord(condition);
        return actionValueResult(pageCommonVO.getPageInfo());
    }

    @RequestMapping(value = "/listForInOutRecordNotPackaged", method = RequestMethod.POST)
    @ApiOperation("查询出入库记录")
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> listForInOutRecordNotPackaged(@RequestBody WarehouseInOutBaseVO condition) throws Exception {
        if (condition == null) {
            condition = new WarehouseInOutBaseVO();
        }
        condition.setOrgId(getOrgId());
        List<WarehouseInOutBaseVO> warehouseInOutBaseVOs = warehouseInventoryService.listForInOutRecordNotPackaged(condition);
        return actionValueResult(warehouseInOutBaseVOs);
    }


    @RequestMapping(value = "/listForInOutRecordGroup", method = RequestMethod.POST)
    @ApiOperation("查询出入库记录汇总")
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> listForInOutRecordGroup(@RequestBody SearchCommonVO<WarehouseInOutBaseVO> condition) throws Exception {
        WarehouseInOutBaseVO warehouseInOutBaseVO = condition.getFilters();
        if (warehouseInOutBaseVO == null) {
            warehouseInOutBaseVO = new WarehouseInOutBaseVO();
        }
        warehouseInOutBaseVO.setOrgId(getOrgId());
        condition.setFilters(warehouseInOutBaseVO);
        PageCommonVO<Object> pageCommonVO = warehouseInventoryService.listForInOutRecordGroup(condition);
        return actionValueResult(pageCommonVO.getPageInfo());
    }


    @RequestMapping(value = "/exportForInOutRecord", method = RequestMethod.POST)
    @ApiOperation("导出非正常入库记录列表")
    @FastMappingInfo(needLogin = true)
    public void exportForInOutRecord(String[] ids) throws Exception {
        warehouseInventoryService.exportForInOutRecord(Arrays.asList(ids));
    }

    @RequestMapping(value = "/exportAllForInOutRecord", method = RequestMethod.POST)
    @ApiOperation("导出全部非正常入库记录列表")
    @FastMappingInfo(needLogin = true)
    public void exportAllForInOutRecord(WarehouseInOutBaseVO condition) throws Exception {
        condition.setOrgId(getOrgId());
        warehouseInventoryService.exportAllForInOutRecord(condition);
    }


    @RequestMapping(value = "/exportAllForInOutRecordSum", method = RequestMethod.POST)
    @ApiOperation("导出全部非正常入库记录列表")
    @FastMappingInfo(needLogin = true)
    public void exportAllForInOutRecordSum(WarehouseInOutBaseVO condition) throws Exception {
        condition.setOrgId(getOrgId());
        warehouseInventoryService.exportAllForInOutRecordGroup(condition);
    }


    @RequestMapping(value = "/updateFrozenState", method = RequestMethod.POST)
    @ApiOperation(value = "更新库存零件冻结状态")
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> updateFrozenState(@RequestBody WarehouseInventoryBatchFrozenVO batchFrozenVO) throws Exception {
        if (null == batchFrozenVO) {
            throw new CommonBusiExceptions(ErrorCode.IllegalArument.getDesc());
        }
        FunctionResult<Object> result = warehouseInventoryService.batchUpdateFrozenState(batchFrozenVO, getOrgId());
        return actionResult(result.getCode(), result.getValue());
    }

    @RequestMapping(value = "/findEnableAndOccupyNum", method = RequestMethod.POST)
    @ApiOperation(value = "发货通知单中查询零件可用库存，意向占用和发货占用")
    @FastMappingInfo(needLogin = true)
    public ActionResult<EnableAndOccupyVO> findEnableAndOccupyNum(String materialNo) throws Exception {
        if (null == materialNo) {
            throw new CommonBusiExceptions(ErrorCode.IllegalArument.getDesc());
        }
        return actionValueResult(warehouseInventoryService.findEnableAndOccupyNum(materialNo, getOrgId(), null));
    }

    @RequestMapping(value = "/exportAll", method = RequestMethod.POST)
    @ApiOperation("导出全部仓库库存记录列表")
    @FastMappingInfo(needLogin = true)
    public void exportAll(WarehouseInventoryVO condition) throws Exception {
        condition.setOrgId(getOrgId());
        warehouseInventoryService.exportAll(condition, "仓库库存数据导出");
    }

    @RequestMapping(value = "/exportAllForDealer", method = RequestMethod.POST)
    @ApiOperation("导出全部客户库存记录列表")
    @FastMappingInfo(needLogin = true)
    public void exportAllForDealer(WarehouseInventoryVO condition) throws Exception {
        String orgId = getOrgId();
        if (StringUtils.isNotBlank(condition.getOrgId())) {
            CompanyDealerDO companyDealerDO = companyDealerMapper.item(Long.valueOf(condition.getOrgId()));
            if (companyDealerDO != null && companyDealerDO.getIsPlatCompany()) {
                condition.setDealerOrgId(companyDealerDO.getPlatOrgId());
            } else {
                return;
            }
        }
        condition.setOrgId(orgId);
        warehouseInventoryService.exportDealerInventoryAll(condition, "客户库存数据导出");
    }

    @RequestMapping(value = "/createObligateOrder", method = RequestMethod.POST)
    @ApiOperation("手动创建预留单")
    @FastMappingInfo(needLogin = true)
    public ActionResult<String> createObligateOrder(@RequestBody ObligateVO obligateVO) throws Exception {
        if (obligateVO == null) {
            throw new CommonBusiExceptions(ErrorCode.IllegalArument.getDesc());
        }
        ErrorCode errorCode;
        try {
            String orgId = getOrgId();
            errorCode = warehouseInventoryService.manualCreateObligateOrder(obligateVO.getId(), obligateVO.getBusinessOrder(), orgId);
        } catch (Exception e) {
            return new ActionResult<>(ErrorCode.Failure.getCode(), e.getMessage());
        }
        return actionResult(errorCode);
    }



    @RequestMapping(value = "/listForQueryDetail", method = RequestMethod.POST)
    @ApiOperation("查询库存记录列表")
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> listForQueryDetail(@RequestBody SearchCommonVO<WarehouseInventoryVO> condition) throws Exception {
        condition.getFilters().setOrgId(getOrgId());
        return actionValueResult(warehouseInventoryService.listForQueryDetail(condition).getPageInfo());
    }

    @RequestMapping(value = "/intentionDetail", method = RequestMethod.POST)
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> intentionDetail(@RequestBody SearchCommonVO<WarehoseIntentionDetialVO> condition) throws Exception {
        WarehoseIntentionDetialVO warehoseIntentionDetialVO = condition.getFilters();
        warehoseIntentionDetialVO.setOrgId(getOrgId());
        condition.setFilters(warehoseIntentionDetialVO);
        PageCommonVO<Object> pageCommonVO = warehouseInventoryService.intentionDetailList(condition);
        return actionValueResult(pageCommonVO.getPageInfo());
    }

    @RequestMapping(value = "/deliveryDetail", method = RequestMethod.POST)
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> deliveryDetailList(@RequestBody SearchCommonVO<WarehoseIntentionDetialVO> condition) throws Exception {
        WarehoseIntentionDetialVO warehoseIntentionDetialVO = condition.getFilters();
        warehoseIntentionDetialVO.setOrgId(getOrgId());
        condition.setFilters(warehoseIntentionDetialVO);
        PageCommonVO<Object> pageCommonVO = warehouseInventoryService.deliveryDetailList(condition);
        return actionValueResult(pageCommonVO.getPageInfo());
    }

    private Integer getIndex(String msg) {
        try {
            if (!msg.startsWith("index&&")) {
                return 0;
            }
            String[] str = msg.split("&&");
            return new Integer(str[1]);
        } catch (Exception e) {
            return 0;
        }
    }

    private String getMsg(String msg) {
        try {
            if (!msg.startsWith("index&&")) {
                return msg;
            }
            String[] str = msg.split("&&");
            return str[2];
        } catch (Exception e) {
            return msg;
        }
    }

    private String getExceptionAllinformation(Exception ex) {
        StringBuilder sOut = new StringBuilder(ex.getMessage() + "\r\n");
        StackTraceElement[] trace = ex.getStackTrace();
        for (StackTraceElement s : trace) {
            sOut.append("\tat " + s + "\r\n");
        }
        return sOut.toString();
    }

    @RequestMapping(value = "/stockAmountList", method = RequestMethod.POST)
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> listStockAmountInfo(
            @RequestBody SearchCommonVO<StockAmountInfo> condition) {
        PageCommonVO<Object> pageCommonVO = null;

        try {
            StockAmountInfo stockAmountInfo = condition.getFilters();
            if (null == stockAmountInfo.getOrgId()) {
                stockAmountInfo.setOrgId(getOrgId());
            }
            condition.setFilters(stockAmountInfo);
            pageCommonVO = warehouseInventoryService.listStockAmountInfo(condition);
        } catch (Exception e) {
            return actionResult(ErrorCode.Failure, e.getMessage());
        }
        return actionValueResult(pageCommonVO.getPageInfo());
    }

    @RequestMapping(value = "/exportStockAmount", method = RequestMethod.POST)
    @ApiOperation("导出库存金额")
    @FastMappingInfo(needLogin = true)
    public void exportStockAmount(StockAmountInfo condition) throws Exception {
        if (condition.getOrgId() == null) {
            condition.setOrgId(getOrgId());
        }
        warehouseInventoryService.exportStockAmount(condition);
    }

    /**
     * @Des 报表管理-->增加仓库库存报表
     * @Date 2020/11/10 18:01
     * @Author wangzhaoyu
     * @Param [searchCondition]
     * @Return yb.ecp.fast.infra.infra.ActionResult
     */
    @RequestMapping(value = "/areaStockList", method = RequestMethod.POST)
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> areaStockList(@RequestBody SearchCommonVO<WarehouseAreaStockQueryParamVO> searchCondition) throws Exception {
        //获取当前登录orgId
        String orgId = getOrgId();
        WarehouseAreaStockQueryParamVO filters = searchCondition.getFilters();
        if (filters == null) {
            filters = new WarehouseAreaStockQueryParamVO();
        }
        filters.setOrgId(orgId);
        searchCondition.setFilters(filters);
        PageCommonVO<WarehouseAreaStockQueryResultVO> result = warehouseInventoryService.areaStockList(searchCondition);
        return ActionResultUtil.successActionResult(result.getPageInfo());
    }

    /**
     * @Des 报表管理-->增加仓库库存报表导出
     * @Date 2020/11/10 18:02
     * @Author wangzhaoyu
     * @Param []
     * @Return void
     */
    @RequestMapping(value = "/areaStockListExport", method = RequestMethod.POST)
    @FastMappingInfo(needLogin = true)
    public void areaStockListExport(WarehouseAreaStockQueryParamVO paramVO, HttpServletResponse response) throws Exception {
        //获取当前登录orgId
        String orgId = getOrgId();
        paramVO.setOrgId(orgId);
        List<WarehouseAreaStockQueryResultVO> warehouseAreaStockQueryResults = warehouseInventoryService.areaStockListExport(paramVO);
        //导出
        invokeExportForAreaStockList(warehouseAreaStockQueryResults, response);
    }

    /**
     * @Des 报表管理-->增加仓库库存报表导出
     * @Date 2020/11/10 18:55
     * @Author wangzhaoyu
     * @Param [warehouseAreaStockQueryResults]
     * @Return void
     */
    private void invokeExportForAreaStockList(List<WarehouseAreaStockQueryResultVO> warehouseAreaStockQueryResults, HttpServletResponse response) {
        String title = "仓库库存导出";
        String[] rowsName = new String[]{"序号", "仓库", "库区", "仓库描述", "仓库金额", "库存数量"};
        List<Object[]> dataList = new ArrayList<>();
        Object[] objs;
        for (int i = 0; i < warehouseAreaStockQueryResults.size(); i++) {
            WarehouseAreaStockQueryResultVO exportVO = warehouseAreaStockQueryResults.get(i);
            objs = new Object[rowsName.length];
            objs[0] = i + 1;
            objs[1] = exportVO.getWarehouseCode();
            objs[2] = exportVO.getAreaCode();
            objs[3] = exportVO.getWarehouseDesc();
            objs[4] = exportVO.getStockAmount();
            objs[5] = exportVO.getCurrentStock();
            dataList.add(objs);
        }
        ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList);
        exportUtil.export(response);
    }


    @RequestMapping(value = "/countEnableInventory", method = RequestMethod.GET)
    @ApiOperation("铲运可用库存信息同步接口")
    @ExternalApiRequest(ApiCheckOptionEnum.OPTION_SECRET)
    public ActionResult<Object> countEnableInventory(String materialsNo) {
        MaterialsEnableStock result = null;
        try {
            result = warehouseInventoryService.countEnableInventory(CompanyConstants.CY_ORG_ID, materialsNo);
        } catch (Exception e) {
            return new ActionResult<>(ErrorCode.Failure.getCode(), e.getMessage());
        }
        return actionValueResult(result);
    }

    @RequestMapping(value = "/countAgentEnableInventory", method = RequestMethod.GET)
    @ApiOperation("铲运代理商可用库存信息查询接口")
    @ExternalApiRequest(ApiCheckOptionEnum.OPTION_SECRET)
    public ActionResult<Object> countEnableInventory(String materialsNo, String sapCode) {
        MaterialsEnableStock result = null;
        try {
            result = warehouseInventoryService.countAgentEnableInventory(CompanyConstants.CY_ORG_ID, sapCode, materialsNo);
        } catch (Exception e) {
            return new ActionResult<>(ErrorCode.Failure.getCode(), e.getMessage());
        }
        return actionValueResult(result);
    }

    @RequestMapping(value = "/transferWarehouseInventoryWithoutBarCode", method = RequestMethod.POST)
    @ApiOperation(value = "非条码零件与储位转移")
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> transferWarehouseInventoryWithoutBarCode(@RequestBody WarehouseInventoryTransferWithOutBarCodeVO warehouseInventoryTransferWithOutBarCodeVO) throws Exception {
        String orgId = getOrgId();
        String userId = getUserId();

        String oldLocationCode = warehouseInventoryTransferWithOutBarCodeVO.getOldLocationCode();

        String newLocationCode = warehouseInventoryTransferWithOutBarCodeVO.getNewLocationCode();

        ErrorCode errorCode = null;
        //储位转移
        if (1 == warehouseInventoryTransferWithOutBarCodeVO.getType()) {
            errorCode = warehouseInventoryService.transferByLocationWithoutBarCode(oldLocationCode, newLocationCode, orgId, userId);
        } else {
            if (CollectionUtils.isEmpty(warehouseInventoryTransferWithOutBarCodeVO.getMaterialNoAndAmounts())) {
                throw new CommonBusiExceptions("零件编号不能为空!");
            }
            errorCode = warehouseInventoryService.transferByMaterialWithoutBarCode(warehouseInventoryTransferWithOutBarCodeVO, orgId, userId);
        }

        return new ActionResult<>(errorCode);

    }

    @RequestMapping(value = "/getInventory4CRM", method = RequestMethod.GET)
    @ExternalApiRequest
    @ApiOperation(value = "获取库存接口")
    public ActionResult<Object> getInventory4CRM(String materialsNo, String sapCode) {
        try {
            return actionValueResult(warehouseInventoryService.getInventory4CRM(materialsNo, sapCode));
        } catch (Exception e) {
            return actionResult(ErrorCode.Failure, e.getMessage());
        }
    }

    /**
     * @Des 塔机首页库存柱状图报表
     * @Date 2020/11/13 15:23
     * @Author wangzhaoyu
     * @Param [type : 0==库存，1==库存金额]
     * @Return yb.ecp.fast.infra.infra.ActionResult
     */
    @RequestMapping(value = "history/report", method = {RequestMethod.GET, RequestMethod.POST})
    public ActionResult<Object> warehouseInventoryHistoryReport(Integer type) throws Exception {
        boolean b = checkWarehouseInventoryHistoryReportParam(type);
        if (b) {
            return ActionResultUtil.successActionResult(new WarehouseInventoryHistoryReportResponse(Collections.emptyList(), Collections.emptyList()));
        }
        WarehouseInventoryHistoryReportResponse result = new WarehouseInventoryHistoryReportResponse();
        //获取需要展示的月份
        Date[] dates = warehouseInventoryHistoryReportMonths();
        //获取横坐表第一个元素（起始月份），作为查询的起始日期
        Date date = dates[0];
        SimpleDateFormat monthFormat = new SimpleDateFormat(MONTH_FORMAT_STR);
        String monthFormatStr = monthFormat.format(date);
        String orgId = getOrgId();
        List<WarehouseInventoryHistoryReportVO> warehouseInventoryHistoryReports = warehouseInventoryHistoryService.warehouseInventoryHistoryReport(orgId, monthFormatStr);

        //使用map记录每个月份对应的下标，用于查询出来的数据匹配到该放到数组的第几位
        Map<String, Integer> monthIndexMap = convertMonthIndex(dates);
        Map<String, BigDecimal[]> datas = new HashMap<>();
        for (WarehouseInventoryHistoryReportVO reportVO : warehouseInventoryHistoryReports) {
            //获取当前数据月份对应的横坐标下标
            String historyTime = reportVO.getHistoryTime();
            Integer monthIndex = monthIndexMap.get(historyTime);
            if (monthIndex == null) {
                continue;
            }
            String warehouseTypeName = reportVO.getWarehouseTypeName();
            warehouseTypeName = StringUtils.isEmpty(warehouseTypeName) ? WarehouseInventoryHistoryReportResponse.NO_WAREHOUSETYPE_NAME : warehouseTypeName;

            collectDatas(type, reportVO, warehouseTypeName, datas, dates, monthIndex);
        }
        //拼接结果并排序
        List<WarehouseInventoryHistoryReportResponse.ReportData> responseDatas = new ArrayList<>();
        for (Map.Entry<String, BigDecimal[]> data : datas.entrySet()) {
            String key = data.getKey();
            BigDecimal[] value = data.getValue();
            WarehouseInventoryHistoryReportResponse.ReportData reportData = result.new ReportData();
            reportData.setWarehouseTypeName(key);
            reportData.setData(value);
            responseDatas.add(reportData);
        }
        result.setMonths(monthAbscissa(dates));
        result.setData(responseDatas);
        result.sortData();
        return ActionResultUtil.successActionResult(result);
    }

    private BigDecimal collectDatas(Integer type, WarehouseInventoryHistoryReportVO reportVO, String warehouseTypeName, Map<String, BigDecimal[]> datas, Date[] dates, int monthIndex) {
        BigDecimal viewNum = null;
        if (type == 0) {//取仓库库存值
            viewNum = reportVO.getInventory();
        } else if (type == 1) {//取仓库库存金额值
            viewNum = reportVO.getInventoryAmount();
        } else {
            viewNum = BigDecimal.ZERO;
        }
        viewNum = viewNum == null ? BigDecimal.ZERO : viewNum;
        if (datas.containsKey(warehouseTypeName)) {
            datas.get(warehouseTypeName)[monthIndex] = viewNum;
        } else {
            BigDecimal[] dataLst = new BigDecimal[dates.length];
            dataLst[monthIndex] = viewNum;
            datas.put(warehouseTypeName, dataLst);
        }
        return viewNum;
    }

    private boolean checkWarehouseInventoryHistoryReportParam(Integer type) {
        return type == null || (type != 0 && type != 1);
    }

    /**
     * @Des库存历史数据手动补充调用接口
     * @Date 2020/11/13 15:59
     * @Author wangzhaoyu
     * @Param [orgId, historyTime]
     * @Return xcmg.device.service.crm.util.ActionResultUtil
     */
    @RequestMapping(value = "history/repair", method = {RequestMethod.GET, RequestMethod.POST})
    public ActionResult<Object> warehouseInventoryHistoryRepair(String orgId, String historyTime) {
        Date now = new Date();
        warehouseInventoryHistoryService.generateWarehouseInventoryHistory(now, historyTime, orgId);
        return ActionResultUtil.successActionResult();
    }

    /**
     * @Des 库存周转报表
     * @Date 2020/12/2 11:44
     * @Author wangzhaoyu
     * @Param [paramVO]
     * @Return yb.ecp.fast.infra.infra.ActionResult
     */
    @RequestMapping(value = "/turnover/report", method = {RequestMethod.GET, RequestMethod.POST})
    public ActionResult<Object> inventoryTurnoverReport(@RequestBody SearchCommonVO<InventoryTurnOverQueryParamVO> condition) throws Exception {
        InventoryTurnOverQueryParamVO paramVO = condition.getFilters();
        String monthStart = paramVO.getMonthStart();
        String monthEnd = paramVO.getMonthEnd();
        if (StringUtils.isEmpty(monthStart) || StringUtils.isEmpty(monthEnd)) {
            return ActionResultUtil.errorActionResult(ErrorCode.IllegalArument.getCode(), "请选择开始月份和结束月份");
        }
        //出库记录的查询中开始时间为前端传过来的月份的开始月份的第一天00：00：00，结束日期为传过来的月份的最后一天59：00：00
        Date monthBegin = ToolTime.getMonthBegin(monthStart);
        Date monthEndTime = ToolTime.getMonthEndTime(monthEnd);
        //开始月份和结束月份都要小于当前月份(暂时这么限制，后期如果要做到可以选择当前月的话则期末库存要从库存表中实时获取，而不是读取库存历史表中的数据)
        if (monthBegin.getTime() > System.currentTimeMillis()) {
            return ActionResultUtil.errorActionResult(ErrorCode.IllegalArument.getCode(), "请选择本月之前的月份作为开始月份");
        }
        if (monthEndTime.getTime() > System.currentTimeMillis()) {
            return ActionResultUtil.errorActionResult(ErrorCode.IllegalArument.getCode(), "请选择本月之前的月份作为结束月份");
        }
        //开始时间与结束时间之间的月份差
        Integer difMonth = ToolTime.getDifMonth(monthBegin, monthEndTime);
        difMonth = difMonth + 1;
        if (difMonth > 12) {
            return ActionResultUtil.errorActionResult(ErrorCode.IllegalArument.getCode(), "开始月份与结束月份不能超过一年");
        }
        //月份处理,期初库存的查询开始时间为前端传过来的开始月份的上一个月月末的时候统计数据（所以前端传过来的开始时间要进行减一个月的操作）
        SimpleDateFormat sdf = new SimpleDateFormat(MONTH_FORMAT_STR);
        Calendar inventoryQueryStartCal = Calendar.getInstance();
        inventoryQueryStartCal.setTime(monthBegin);
        inventoryQueryStartCal.add(Calendar.MONTH, -1);
        Date inventoryQueryStartDate = inventoryQueryStartCal.getTime();
        String inventoryQueryStartDateStr = sdf.format(inventoryQueryStartDate);
        //月份处理，期末库存的查询结束时间为前端传过来的月份
        String inventoryQueryEndDateStr = sdf.format(monthEndTime);

        String materialsNo = paramVO.getMaterialsNo();
        String materialsDesc = paramVO.getMaterialsDesc();
        String orgId = getOrgId();
        PageCommonVO<WarehouseInventoryTurnOverResultVO> warehouseInventoryTurnOverResult = warehouseInventoryHistoryService.turnoverReport(orgId, condition.getPageSize(), condition.getPageNum(), monthBegin, monthEndTime,
                inventoryQueryStartDateStr, inventoryQueryEndDateStr, materialsNo, materialsDesc);
        //拼接开始月份，结束月份，库存周转天数
        //计算时间段天数
        Integer difDays = ToolTime.getDifDays(monthBegin, monthEndTime);
        for (WarehouseInventoryTurnOverResultVO resultVO : warehouseInventoryTurnOverResult.getPageInfoList()) {
            BigDecimal beginAmount = resultVO.getBeginAmount();
            BigDecimal endAmount = resultVO.getEndAmount();
            BigDecimal outAmount = resultVO.getOutAmount();
            //库存周转天数=时间段天数x(1/2)x(期初库存数量+期末库存数量）/时间段出库量
            BigDecimal turnoverDays = BigDecimal.valueOf(difDays.doubleValue())
                    .divide(new BigDecimal("2"), 2, BigDecimal.ROUND_HALF_UP)
                    .multiply(beginAmount.add(endAmount))
                    .divide(outAmount, 2, BigDecimal.ROUND_HALF_UP);
            resultVO.setTurnoverDays(turnoverDays);
            resultVO.setStartMonth(monthStart);
            resultVO.setEndMonth(monthEnd);
        }
        return ActionResultUtil.successActionResult(warehouseInventoryTurnOverResult.getPageInfo());
    }


    /**
     * @Des 库存周转报表导出
     * @Date 2020/12/2 19:11
     * @Author wangzhaoyu
     * @Param [condition]
     * @Return yb.ecp.fast.infra.infra.ActionResult
     */
    @RequestMapping(value = "/turnover/export", method = {RequestMethod.GET, RequestMethod.POST})
    @FastMappingInfo(needLogin = true)
    public ActionResult<Object> inventoryTurnoverExport(InventoryTurnOverQueryParamVO paramVO, HttpServletResponse response) throws Exception {
        String monthStart = paramVO.getMonthStart();
        String monthEnd = paramVO.getMonthEnd();
        if (StringUtils.isEmpty(monthStart) || StringUtils.isEmpty(monthEnd)) {
            return ActionResultUtil.errorActionResult(ErrorCode.IllegalArument.getCode(), "请选择开始月份和结束月份");
        }
        //出库记录的查询中开始时间为前端传过来的月份的开始月份的第一天00：00：00，结束日期为传过来的月份的最后一天59：00：00
        Date monthBegin = ToolTime.getMonthBegin(monthStart);
        Date monthEndTime = ToolTime.getMonthEndTime(monthEnd);
        //开始月份和结束月份都要小于当前月份(暂时这么限制，后期如果要做到可以选择当前月的话则期末库存要从库存表中实时获取，而不是读取库存历史表中的数据)
        if (monthBegin.getTime() > System.currentTimeMillis()) {
            return ActionResultUtil.errorActionResult(ErrorCode.IllegalArument.getCode(), "请选择本月之前的月份作为开始月份");
        }
        if (monthEndTime.getTime() > System.currentTimeMillis()) {
            return ActionResultUtil.errorActionResult(ErrorCode.IllegalArument.getCode(), "请选择本月之前的月份作为结束月份");
        }
        //开始时间与结束时间之间的月份差
        Integer difMonth = ToolTime.getDifMonth(monthBegin, monthEndTime);
        difMonth = difMonth + 1;
        if (difMonth > 12) {
            return ActionResultUtil.errorActionResult(ErrorCode.IllegalArument.getCode(), "开始月份与结束月份不能超过一年");
        }
        //月份处理,期初库存的查询开始时间为前端传过来的开始月份的上一个月月末的时候统计数据（所以前端传过来的开始时间要进行减一个月的操作）
        SimpleDateFormat sdf = new SimpleDateFormat(MONTH_FORMAT_STR);
        Calendar inventoryQueryStartCal = Calendar.getInstance();
        inventoryQueryStartCal.setTime(monthBegin);
        inventoryQueryStartCal.add(Calendar.MONTH, -1);
        Date inventoryQueryStartDate = inventoryQueryStartCal.getTime();
        String inventoryQueryStartDateStr = sdf.format(inventoryQueryStartDate);
        //月份处理，期末库存的查询结束时间为前端传过来的月份
        String inventoryQueryEndDateStr = sdf.format(monthEndTime);

        String materialsNo = paramVO.getMaterialsNo();
        String materialsDesc = paramVO.getMaterialsDesc();
        String orgId = getOrgId();
        List<WarehouseInventoryTurnOverResultVO> warehouseInventoryTurnOverResult = warehouseInventoryHistoryService.turnoverExport(orgId, monthBegin, monthEndTime,
                inventoryQueryStartDateStr, inventoryQueryEndDateStr, materialsNo, materialsDesc);
        //拼接开始月份，结束月份，库存周转天数
        //计算时间段天数
        Integer difDays = ToolTime.getDifDays(monthBegin, monthEndTime);
        for (WarehouseInventoryTurnOverResultVO resultVO : warehouseInventoryTurnOverResult) {
            BigDecimal beginAmount = resultVO.getBeginAmount();
            BigDecimal endAmount = resultVO.getEndAmount();
            BigDecimal outAmount = resultVO.getOutAmount();
            //库存周转天数=时间段天数x(1/2)x(期初库存数量+期末库存数量）/时间段出库量
            BigDecimal turnoverDays = BigDecimal.valueOf(difDays.doubleValue())
                    .divide(new BigDecimal("2"), 2, BigDecimal.ROUND_HALF_UP)
                    .multiply(beginAmount.add(endAmount))
                    .divide(outAmount, 2, BigDecimal.ROUND_HALF_UP);
            resultVO.setTurnoverDays(turnoverDays);
            resultVO.setStartMonth(monthStart);
            resultVO.setEndMonth(monthEnd);
        }
        turnoverExport(warehouseInventoryTurnOverResult, response);
        return null;
    }

    private void turnoverExport(List<WarehouseInventoryTurnOverResultVO> warehouseInventoryTurnOverResult, HttpServletResponse response) {
        String title = "库存周转导出";
        String[] rowsName = new String[]{"序号", "开始月份", "结束月份", "零件编码", "零件名称", "期初库存数量", "期末库存数量", "出库量", "库存周转天数"};
        List<Object[]> dataList = new ArrayList<>();
        Object[] objs;
        for (int i = 0; i < warehouseInventoryTurnOverResult.size(); i++) {
            WarehouseInventoryTurnOverResultVO exportVO = warehouseInventoryTurnOverResult.get(i);
            objs = new Object[rowsName.length];
            objs[0] = i + 1;
            objs[1] = exportVO.getStartMonth();
            objs[2] = exportVO.getEndMonth();
            objs[3] = exportVO.getMaterialsNo();
            objs[4] = exportVO.getMaterialsDesc();
            objs[5] = exportVO.getBeginAmount();
            objs[6] = exportVO.getEndAmount();
            objs[7] = exportVO.getOutAmount();
            objs[8] = exportVO.getTurnoverDays();
            dataList.add(objs);
        }
        ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList);
        exportUtil.export(response);
    }


    /**
     * @Des 横坐标
     * @Date 2020/11/13 15:20
     * @Author wangzhaoyu
     * @Param [dates]
     * @Return java.util.List<java.lang.String>
     */
    private List<String> monthAbscissa(Date[] dates) {
        List<String> result = new ArrayList<>();
        SimpleDateFormat monthFormat = new SimpleDateFormat("yyyy年MM月");
        for (int i = 0; i < dates.length; i++) {
            result.add(monthFormat.format(dates[i]));
        }
        return result;
    }

    private Map<String, Integer> convertMonthIndex(Date[] dates) {
        SimpleDateFormat monthFormat = new SimpleDateFormat(MONTH_FORMAT_STR);
        Map<String, Integer> result = new HashMap<>();
        for (int i = 0; i < dates.length; i++) {
            Date date = dates[i];
            String format = monthFormat.format(date);
            result.put(format, i);
        }
        return result;
    }

    /**
     * @Des 拼接横坐标表数组, 往前数十二个月
     * @Date 2020/11/13 13:38
     * @Author wangzhaoyu
     * @Param [now]
     * @Return java.util.List<java.lang.String>
     */
    private static Date[] warehouseInventoryHistoryReportMonths() {
        Date[] last12Months = new Date[12];
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) - 1);
        //初始换当前日期为本月一号
        cal.set(Calendar.DAY_OF_MONTH, 1);
        for (int i = 0; i < 12; i++) {
            last12Months[11 - i] = cal.getTime();
            cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) - 1); //逐次往前推1个月
        }
        return last12Months;
    }
}
